﻿using System;
using System.Collections.Generic;
using Business.Entity.Sped;
using Business.Entity.Vendas.Pedido;
using Business.Enum;
using NHibernate;

namespace Business.Entity.Contabil
{

    public class LancamentoRepository : RepositoryBase<Lancamento>, IDisposable
    {
        

        public static void GeraPartida(Lancamento lanc)
        {
            
            var pValor = VerificaPartida(lanc, lanc.TipoLancmento.ContaPartidaValor);
            var cpValor = VerificaPartida(lanc, lanc.TipoLancmento.ContaContraPartidaValor);
            var pDesconto = VerificaPartida(lanc, lanc.TipoLancmento.ContaPartidaDesconto);
            var cpDesconto = VerificaPartida(lanc, lanc.TipoLancmento.ContaContraPartidaDesconto);
            var pJuros = VerificaPartida(lanc, lanc.TipoLancmento.ContaPartidaJuros);
            var cpJuros = VerificaPartida(lanc, lanc.TipoLancmento.ContaContraPartidaJuros);

            pValor.Valor += lanc.Valor;
            cpValor.Valor += lanc.Valor;
            if (lanc.Juros > 0)
            {
                if (pJuros == null)
                {
                    pValor.Valor += lanc.Juros;

                }
                else
                {
                    pJuros.Valor += lanc.Juros;

                }
                if (cpJuros == null)
                {
                    cpValor.Valor += lanc.Juros;
                }
                else
                {
                    cpJuros.Valor += lanc.Juros;
                }
            }
            if (lanc.Desconto > 0)
            {
                if (pDesconto == null)
                {
                    pValor.Valor -= lanc.Desconto;
                }
                else
                {
                    pDesconto.Valor -= lanc.Desconto;
                }
                if (cpDesconto == null)
                {
                    cpValor.Valor += lanc.Desconto;
                }
                else
                {
                    cpDesconto.Valor += lanc.Desconto;
                }
            }
        }

        public static PartidasLancamento VerificaPartida(Lancamento lanc, PlanoContaReferencial planoConta)
        {
            if (planoConta == null)
            {
                return null;
            }
            foreach (var partida in lanc.Partidas)
            {
                if (partida.PlanoConta.Codigo.Equals(planoConta.Codigo))
                {
                    return partida;
                }
            }
            // Caso não encontre uma partida correspondente ao código no lançamento cria uma nova partida.
            RepositoryBase<PlanoContaReferencial>.Session = RepositoryBase<Pedido>.Session;
            var p = new PartidasLancamento()
            {
                PlanoConta = PlanoContaReferencialRepository.GetByCodigoConta(planoConta.Codigo)
            };
            lanc.Partidas.Add(p);
            return p;
        }

        private static void EfetuarMovimentacaoContaByPartidas(ISession session, PlanoContaReferencial planoConta, decimal valor)
        {

            if (planoConta.NaturezaConta == NaturecaConta.Ativo)
            {
                PlanoContaReferencialRepository.CreditarConta(session,
                    planoConta,
                    valor);
            }
            if (planoConta.NaturezaConta == NaturecaConta.Passivo)
            {
                PlanoContaReferencialRepository.DebitarConta(session,
                    planoConta,
                    valor);
            }
        }

        public static void Save(Lancamento entity)
        {

            ISession session = GetSession();
            ITransaction transaction = session.BeginTransaction();
            try
            {
                GeraPartida(entity);
                session.Save(entity);
                transaction.Commit();
            }
            catch (Exception)
            {
                transaction.Rollback();
                throw;
            }
        }

        public void Dispose()
        {

        }

        public static IList<Lancamento> GetListByPeriodoLancamento(DateTime inicio, DateTime fim)
        {
            return GetListAtivos(GetQueryOver().Where(lancamento =>
                lancamento.DataLancamento >= inicio && lancamento.DataLancamento <= fim));
        }

        public static IList<Lancamento> GetListByPeriodoVencimento(DateTime inicio, DateTime fim)
        {
            return GetListAtivos(GetQueryOver().Where(lancamento =>
                lancamento.Vencimento >= inicio && lancamento.Vencimento <= fim));
        }
        public static IList<Lancamento> GetListByMesLancamento(int mes, int ano)
        {
            return GetListAtivos(GetQueryOver().Where(lancamento =>
                lancamento.DataLancamento.Month == mes && lancamento.DataLancamento.Year == ano));
        }
        public static IList<Lancamento> GetListByMesVencimento(int mes, int ano)
        {
            return GetListAtivos(GetQueryOver().Where(lancamento =>
                lancamento.Vencimento.Month == mes && lancamento.Vencimento.Year == ano));
        }

        public static IList<Lancamento> GetListEntradasPeriodo(DateTime inicio, DateTime fim)
        {
            TipoLancamento t = null;

            var c = GetQueryOver()
                .Where(lancamento => lancamento.DataLancamento >= inicio &&
                    lancamento.DataLancamento <= fim)
                .Inner.JoinQueryOver(
                lancamento => lancamento.TipoLancmento, () => t)
                .Where(lancamento => lancamento.Credito);
            return c.List<Lancamento>();
        }
    }


}

